package edu.johnpank.libassistant.controllers

import edu.johnpank.libassistant.entity.Book
import edu.johnpank.libassistant.entity.BorrowedBook
import edu.johnpank.libassistant.entity.User
import edu.johnpank.libassistant.enums.Role
import edu.johnpank.libassistant.services.BookService
import edu.johnpank.libassistant.services.BorrowedBookService
import edu.johnpank.libassistant.services.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.ComponentScan
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.validation.BindingResult
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import java.time.LocalDateTime
import java.time.ZoneOffset
import javax.validation.Valid

@Controller
@ComponentScan
class LibrarianController(
    @Autowired
    private val bookService: BookService,
    private val userService: UserService,
    private val borrowedBookService: BorrowedBookService,
    private val passwordEncoder: PasswordEncoder
) {

    private var currentUser: User = User()
    private var borrowBookList: MutableList<Book> = mutableListOf()

    //region showMainLibrarianPage
    @GetMapping("librarian/libr_main_page")
    fun showMainLibrarianPage(): String{
        return "librarian/libr_main_page"
    }
    //endregion

    //region addBook
    @GetMapping("/librarian/addBookPage")
    fun showAddBookPage(@ModelAttribute("newBook") book: Book): String{
        return "/librarian/add_book_page"
    }

    @PostMapping("/librarian/addBook")
    fun addBook(@ModelAttribute("newBook") @Valid book: Book,
                            bindingResult: BindingResult,
                            model: Model
    ): String {

//        userValidator.validate(user, bindingResult)
//        if (bindingResult.hasErrors())
//            return "/librarian/add_libr_admin_page"

        bookService.addBook(book)
        return "redirect:/librarian/addBookPage"
    }
    //endregion

    //region showBookList
    @GetMapping("/librarian/bookListPage")
    fun showUserListPage(model: Model): String{
        model.addAttribute("books", bookService.getAllBook().toList())
        return "/librarian/book_list_page"
    }
    //endregion

    //region editBook
    @GetMapping("/librarian/updateBookInfo")
    fun showBookInfoPage(@RequestParam("bookId") id: Long,
                         model: Model): String{
        model.addAttribute("book", bookService.getBookById(id))

        return "/librarian/edit_book_page"
    }

    @PostMapping("/librarian/updateBook")
    fun updateBookInfo(@ModelAttribute("book") book: Book,
                       bindingResult: BindingResult,
                       model: Model
    ): String {

        val updatingBook = bookService.getBookByIsbn(book.isbn)
        updatingBook.author = book.author
        updatingBook.title = book.title
        updatingBook.year = book.year
        updatingBook.city = book.city
        updatingBook.publisher = book.publisher
        updatingBook.genre = book.genre
        updatingBook.circulation = book.circulation
        updatingBook.pages = book.pages
        updatingBook.isbn = book.isbn
        updatingBook.barcode = book.barcode
        updatingBook.block = book.block
        updatingBook.subBlock = book.subBlock
        updatingBook.shelfNumber = book.shelfNumber
        updatingBook.comment = book.comment


        if (bindingResult.hasErrors())
            return "/librarian/add_book_page"

        bookService.updateBook(updatingBook)

        return "redirect:/librarian/bookListPage"
    }
    //endregion

    //region deleteBook
    @GetMapping("/librarian/deleteBook")
    fun deleteBook(@RequestParam("bookId") id: Long,
                   model: Model): String{
        val book = bookService.getBookById(id)
        bookService.deleteBook(book)

        return "redirect:/librarian/bookListPage"
    }
    //endregion

    //region findBook
    @GetMapping("/librarian/findBookPage")
    fun showFindBookPage(model: Model): String{
        return "/librarian/find_book_page"
    }

    @GetMapping("/librarian/findBook")
    fun showFindBookResultPage(@RequestParam("search") search: String,
                               model: Model): String{


        model.addAttribute("books", bookService.findBookByContainedString(search))
        return "/librarian/book_list_page"
    }


    //endregion

    //region confirmUser
    //find User
    @GetMapping("/librarian/confirmUserPage")
    fun showLibrFindUserPage(model: Model): String{
        return "/librarian/lbr_find_user_page"
    }

    @GetMapping("/librarian/findUser")
    fun showLibrFindUserResultPage(@RequestParam("search") search: String,
                               model: Model): String{

        model.addAttribute("users", userService.findUserByString(search))
        return "/librarian/libr_user_list_page"
    }

    //confirm user
    @GetMapping("/librarian/confirmUser")
    fun confirmUser(@RequestParam("userId") id: Long,
                   model: Model): String{
        val user = userService.getUserById(id)

        user.isConfirmed = true
        userService.updateUser(user)

        return "/librarian/libr_main_page"
    }

    //endregion

    //regionEditUser

    @GetMapping("/librarian/showUserInfo")
    fun showUserInfoLibrPage(@RequestParam("userId") id: Long,
                         model: Model): String{

        val user = userService.getUserById(id)
        if (user.roles.contains(Role.ROLE_READER)){
            model.addAttribute("user", user)
            return "/librarian/libr_edit_user_page"
        }

        return "/librarian/libr_main_page"
    }

    @PostMapping("/librarian/updateUser")
    fun updateUserInfo(@ModelAttribute("user") user: User,
                       bindingResult: BindingResult,
                       model: Model
    ): String {

        val updatingUser = userService.getUserByLogin(user.login).get()
        updatingUser.login = user.login
        updatingUser.firstName = user.firstName
        updatingUser.lastName = user.lastName
        updatingUser.login = user.login
        updatingUser.email = user.email
        updatingUser.isAdmin = user.isAdmin
        updatingUser.isLibrarian = user.isLibrarian
        updatingUser.isConfirmed = user.isConfirmed
        updatingUser.regDate = user.regDate

        if (user.password.length < 59) updatingUser.password = passwordEncoder.encode(user.password) else updatingUser.password = user.password



        if (bindingResult.hasErrors())
            return "/admin/edit_user_page"

        userService.updateUser(updatingUser)

        return "/librarian/libr_main_page"
    }

    //endregion

    //region borrowBook

    @GetMapping("/librarian/borrowReturnBookPage")
    fun showUserListForBorrowBook(model: Model): String{
//        currentUser = User()
        model.addAttribute("currentUser", currentUser)
        model.addAttribute("borrowBookList", borrowBookList)
        return "/librarian/borrow_return_book"
    }


    //search user for get book
    @PostMapping("/librarian/findUserForGetBook", params= ["action=search"])
    fun showUserListForBorrowBook(@RequestParam("search") search: String,
                                  model: Model): String{
//
//        println("UserAction: search")
//        println("search ${search}")

        model.addAttribute("users", userService.findUserByString(search))
        return "/librarian/libr_user_list_borr_page"
    }

    @PostMapping("/librarian/findUserForGetBook", params= ["action=clear"])
    fun clearCurrentUser(model: Model): String{

//        println("UserAction: clear")
//        println("search ${search}")

        currentUser = User()
        borrowBookList.clear()
        model.addAttribute("currentUser", currentUser)
        model.addAttribute("borrowBookList", borrowBookList)
        return "/librarian/borrow_return_book"
    }

    @GetMapping("/librarian/setCurrentUser")
    fun setCurrentUser(@RequestParam("userId") id: Long,
                       model: Model): String {

        currentUser = userService.getUserById(id)
        for(borrowedBook in borrowedBookService.getAllNotReturnedBookByReader(id)){
            borrowBookList.clear()
            borrowBookList.add(bookService.getBookById(borrowedBook.bookId))
        }

        model.addAttribute("currentUser", currentUser)
        model.addAttribute("borrowBookList", borrowBookList)
        return "/librarian/borrow_return_book"

    }

    @PostMapping("/librarian/borrowBook", params= ["action=searchBook"])
    fun showSearchBookForBorrow(model: Model): String{

        println("UserAction: searchBook")

        return "/librarian/find_book_for_borrow_page"
    }

    @GetMapping("/librarian/findBookForBorrow")
    fun showFindBookForBorrowResultPage(@RequestParam("search") search: String,
                               model: Model): String{

        model.addAttribute("books", bookService.findBookByContainedString(search))
        return "/librarian/book_list_for_borrow_page"
    }

    @GetMapping("/librarian/addBookToBorrowList")
    fun addBookToBorrowList(@RequestParam("bookId") id: Long,
                   model: Model): String{
        val book = bookService.getBookById(id)
        borrowBookList.add(book)

        return "redirect:/librarian/borrowReturnBookPage"
    }

    @PostMapping("/librarian/borrowBook", params= ["action=borrow"])
    fun borrowBook(model: Model): String{

        for (book in borrowBookList){
            val borrowedBook = BorrowedBook()
            borrowedBook.bookId = book.id!!
            borrowedBook.readerId = currentUser.id!!
            borrowedBook.borrowDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) * 1000
//            borrowedBook.returnDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) * 1000 + (14*24*60*60*1000) //day*hour*min*sec*milsec
            borrowedBook.returnDate = 0L
            borrowedBook.returned = false

            println(borrowedBook)
            println(currentUser)

            if (!borrowedBookService.checkBookIsNotReturned(borrowedBook.bookId)){
                borrowedBookService.addBorrowedBook(borrowedBook)
            }

        }

        println("book is borrowed")

        currentUser = User()
        borrowBookList.clear()
        return "redirect:/librarian/borrowReturnBookPage"
    }

    @GetMapping("/librarian/deleteBookFromBorrowList")
    fun deleteBookFromBorrowList(@RequestParam("bookId") id: Long,
                             model: Model): String{

        var bookForRemove = Book()
        for(book in borrowBookList){
            if (book.id == id)
                bookForRemove = book
        }
        borrowBookList.remove(bookForRemove)

        model.addAttribute("currentUser", currentUser)
        model.addAttribute("borrowBookList", borrowBookList)
        return "/librarian/borrow_return_book"
    }

    @GetMapping("/librarian/returnBook")
    fun returnBook(@RequestParam("bookId") id: Long,
                   model: Model): String {

        //update db row
        if (!borrowedBookService.getBorrowedBookForReturn(currentUser.id!!, id).isEmpty){
            val returnedBorrowedBook: BorrowedBook = borrowedBookService.getBorrowedBookForReturn(currentUser.id!!, id).get()
            returnedBorrowedBook.returnDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) * 1000
            returnedBorrowedBook.returned = true
            borrowedBookService.updateBorrowedBook(returnedBorrowedBook)
        }

        //update book list
        var bookForRemove = Book()
        for(book in borrowBookList){
            if (book.id == id)
                bookForRemove = book
        }
        borrowBookList.remove(bookForRemove)


        model.addAttribute("currentUser", currentUser)
        model.addAttribute("borrowBookList", borrowBookList)
        return "/librarian/borrow_return_book"
    }


    //endregion



}